<!-- BdPopup.vue -->
<template>
  <div v-show="attrsCopy.show">
    <van-popup ref="popupRef" v-bind="attrsCopy" @open="openFn">
      <slot></slot>
    </van-popup>
  </div>
</template>

<script>
import { defineComponent } from "vue";
import { useGlobalStore } from "~~/store/global";
/**
 * @description: 二次封装 van-popup
 * 解决:
 * 1. 解决弹窗展示优先级问题: 当有弹窗展示的时候,不会在叠加展示(系统自动弹窗);如有"系统自动弹窗"等当前弹窗消失2秒(默认)以后,在自动弹出;
 * 2.
 * 注意:
 * 1. 每个组件都是一个单独的实例;
 * 2. 数据是存在 store 中的
 * 3. popupId 一定要唯一
 * 4. popupId 要在 weights 中备注优先级;方便后续维护
 */

// 弹窗优先级,key == popupId 这里不区分页面,只定义权重; 值越小优先级越高
// const weights = {
//   lotteryV3SettlementResult: 2, // 结算弹窗
//   lotteryV3Desc: 4, // 奖励说明弹窗
//   lotteryV3BetInfoPopup: 4, // 抽奖 V3 下注弹窗
// };

export default defineComponent({
  name: "bdPopup",
  // inheritAttrs: false,
  setup(props, { attrs, emit }) {
    // console.log("popup attrs:", attrs);

    const globalStore = useGlobalStore();
    // 复制一份,数据源
    const attrsCopy = ref(JSON.parse(JSON.stringify(attrs)));

    /**
     * @description: 打开弹出层时立即触发
     */
    const openFn = () => {
      console.log("打开弹出层时立即触发", attrsCopy.value.show);
      emit("open");
    };

    /**
     * @description: 延迟 2 秒展示弹窗
     */
    const setTimeoutPopupTsk = () => {
      // 按照优先级取出弹窗;并且在指定页面弹出
      setTimeout(() => {
        if (globalStore.$state.popupQueues) {
          // 1. 取出当前页面 key
          const reoute = useRoute(); // const regex = /\/lottery-v3$/;
          // console.log("reoute:", reoute);
          if (
            globalStore.$state.popupQueues[reoute.path] &&
            globalStore.$state.popupQueues[reoute.path].length > 0
          ) {
            const popupInfo = globalStore.$state.popupQueues[reoute.path].pop();
            popupInfo.show = true;
          }
        }
      }, 2000);
    };

    onMounted(() => {});

    /**
     * @description: 关闭弹出层且动画结束后触发
     */
    const show_watch = watch(
      () => attrs.show,
      (newVal, oldVal) => {
        console.log(oldVal, "== BD popup弹窗 ==>", newVal);
        // 1. true
        if (newVal) {
          // 1.1 有正在显示的弹窗
          if (globalStore.$state.isShowIngPopupId) {
            // 1.1.1 当前,有弹窗显示,后面的弹窗不在显示
            attrsCopy.value.show = false;
            console.warn("正在展示:", globalStore.$state.isShowIngPopupId);
            // 1.1.2 保存要展示的弹窗,手动点击的一般不会出现叠加的场景
            const reoute = useRoute(); // const regex = /\/lottery-v3$/;
            // console.log("reoute:", reoute);
            globalStore.$patch((state) => {
              if (state.popupQueues[reoute.path]) {
                state.popupQueues[reoute.path].push(attrsCopy.value);
                // 1.1.3 按照优先级排序
                state.popupQueues[reoute.path] = state.popupQueues[
                  reoute.path
                ].sort(
                  (a, b) => Number(b.weights || 99) - Number(a.weights || 99)
                );
              } else {
                state.popupQueues[reoute.path] = [attrsCopy.value];
              }
            });
          }
          // 1.2 没有
          else {
            // 1.2.1 赋值,改状态
            if (!attrsCopy.value.show) attrsCopy.value.show = true;
            globalStore.$patch((state) => {
              state.isShowIngPopupId = attrsCopy.value.popupId;
            });
          }
        }
        // 2. false
        else {
          // 2.1 如果是当前弹窗隐藏,就更改状态
          if (attrsCopy.value.popupId == globalStore.$state.isShowIngPopupId) {
            globalStore.$patch((state) => {
              state.isShowIngPopupId = "";
            });
            attrsCopy.value.show = false;
          }
          // emit("update:show", false);
          // 2.2 执行任务队列,看看有没有需要展示的弹窗
          setTimeoutPopupTsk();
        }
      },
      {
        immediate: true,
      }
    );

    onBeforeUnmount(() => {
      // 1.
      show_watch && show_watch();
      // 2. 如果,是直接销毁当前弹窗,也要更改状态
      if (attrsCopy.value.popupId == globalStore.$state.isShowIngPopupId) {
        console.warn("关闭弹窗:", attrsCopy.value.popupId);
        globalStore.$patch((state) => {
          state.isShowIngPopupId = "";
        });
      }
      // 3. 销毁的弹窗,是否在任务队列中,存在则删除(这里有两种场景:1.手动销毁 2.主页面销毁,子组件被动销毁)
      if (globalStore.$state.popupQueues) {
        const keys = Object.keys(globalStore.$state.popupQueues);
        keys.forEach((key) => {
          globalStore.$patch((state) => {
            state.popupQueues[key] = state.popupQueues[key].filter(
              (e) => e.popupId != attrsCopy.value.popupId
            );
          });
        });
      }
      // 4. 执行任务队列,看看有没有需要展示的弹窗
      setTimeoutPopupTsk();
    });

    return {
      attrsCopy,
      openFn,
    };
  },
});
</script>

<style lang="scss" scoped>
// 自定义弹窗样式
.custom {
  margin: 0 !important;
  width: 100vw !important;
  max-width: initial;
}

.padding25-30 {
  padding: 0 25 * 2px 30 * 2px 25 * 2px !important;
}
</style>
